home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1999 / MacHack 1999.toast / The Hacks / AltiVec Effect / Effect.c < prev    next >
Encoding:
Text File  |  1999-06-25  |  29.7 KB  |  1,064 lines  |  [TEXT/CWIE]

  1. /*
  2.     Dimmer2Effect.c - a sample QuickTime video effect.
  3.     
  4.     This effect uses a single source as input, and renders that source with
  5.     a dim value that starts at full on, and ramps to full off.  This isn't very
  6.     useful as a real effect, but shows instead how to create an effect.
  7.     
  8.     READ THIS PARAGRAPH BEFORE DOING ANYTHING ELSE IN THIS FILE:
  9.     To find things to change to implement your effect, seach for *** CHANGE ***.  
  10.     Code that will require modification is bracketted by CHANGE/END CHANGE.
  11.     
  12.     There are eleven places to change code, and one place where you write new
  13.     code that implements your actual effect.  MAKE SURE YOU LOOK AT ALL OF THEM.
  14.     
  15.     *IMPORTANT*
  16.     
  17.     You MUST also ensure that the Effect.r file is kept in sync with this code.
  18.     In particular it is very important that you update the 'atms' resource
  19.     description so that the parameters of your effect are correctly described.
  20.     Full details of the format of the 'atms' resource can be found in the Effects
  21.     chapter of the QT 3.0 documentation
  22.     
  23.     ALSO PLEASE NOTE THAT THE LINK WARNING ABOUT THE COMPONENT DISPATCH ENTRY POINT
  24.     NOT BEING A ROUTINE DESCRIPTOR IS NORMAL AND CAN BE IGNORED!
  25.     
  26.     written by Tom Dowdy and Dan Crow
  27.     copyright © 1997-1998 Apple Computer, Inc.
  28.     All rights reserved.
  29. */
  30.  
  31.  
  32. // --------------------------------------------------------------------------------------
  33. // INCLUDES
  34. // --------------------------------------------------------------------------------------
  35.  
  36. #include <MacMemory.h>
  37. #include <Resources.h>
  38. #include <Quickdraw.h>    
  39. #include <QDOffscreen.h>
  40. #include <OSUtils.h>
  41. #include <Errors.h>
  42. #include <FixMath.h>
  43. #include <Movies.h>
  44. #include <Endian.h>
  45. #include <ImageCodec.h>
  46.  
  47. #include "EffectDefinitions.h"
  48.  
  49. #if PRAGMA_STRUCT_ALIGN
  50.     #pragma options align=mac68k
  51. #endif
  52.  
  53. #include "EffectUtilities.h"
  54.  
  55.  
  56. // --------------------------------------------------------------------------------------
  57. // INTERNAL DEFINES
  58. // --------------------------------------------------------------------------------------
  59.  
  60. // *** CHANGE *** This defines the number of frames that can be queued for
  61. // asynchronous rendering by this effect.  The value 0 indicates the effect
  62. // runs synchronously.
  63. #define kMaxAsyncFrames        0
  64. // *** END CHANGE ***
  65.  
  66. // *** CHANGE *** Change if your effect accepts multiple sources.  This value
  67. // is the maximum number of sources this effect operates on.
  68. #define    kMaxSources            2
  69. // *** END CHANGE ***
  70.  
  71. // --------------------------------------------------------------------------------------
  72. // INTERNAL TYPEDEFS
  73. // --------------------------------------------------------------------------------------
  74.  
  75. // Structure used to store inforation about each source
  76. typedef struct SourceRecord {                        
  77.     CDSequenceDataSourcePtr    src;
  78.     void                    *srcBaseAddr;
  79.     long                    srcRowBytes;
  80. } SourceRecord;
  81.  
  82. // This is the structure used to store information for drawing a single frame of the effect
  83. typedef struct BlitGlobals {                            
  84.     SourceRecord        sources[kMaxSources];    // inputs
  85.  
  86.     void                *dstBaseAddr;            // output base address
  87.     long                dstRowBytes;            // output row bytes
  88.     long                height;                    // output height
  89.     long                width;                    // output width
  90.     short                destDepth;                // output depth
  91.     OSType                dstPixelFormat;            // output pixel format
  92.     
  93.     // *** CHANGE *** Here is where we store values relating to a single frame
  94.     // of the effect.  These are the parameters to the effect, modified by the
  95.     // percentage into the effect which we are.
  96.     
  97.     long                direction;
  98.     short                dimValue;                // dimming value, from 0 to 255
  99.     
  100.     long    iIntegrity;
  101.     UInt8*    puiRandoms;
  102.     UInt8*    puiBrightnessRoll;
  103.     UInt8*    puiBRStart;
  104.     UInt8*    puiBREnd;
  105.     // *** END CHANGE ***
  106. } BlitGlobals;
  107.  
  108.  
  109. // global data per instance. This holds data for the entire effect as it runs its course.
  110. typedef struct EffectGlobals
  111.     {
  112.     ComponentInstance    self;        // ourselves
  113.     ComponentInstance    target;        // top of the calling chain
  114.     ComponentInstance    delegate;    // if we can't handle an effect, this one can
  115.     
  116.     BlitGlobals            blitter;    // information for drawing the data
  117.     OSType                **wantedDestinationPixelTypeH;
  118.     
  119.     #if kMaxAsyncFrames > 0
  120.         volatile short    asyncCount;    // number of outstanding frames we have        
  121.     #endif
  122.     
  123.     // parameter/source/dest seed tracking
  124.     long                        initialized;
  125.     long                        frameNumber;            
  126.     long                        virtualDuration;
  127.     long                        majorSourceChangeSeed;
  128.     
  129.     TweenGlobals                tweenGlobals;
  130.  
  131.     // *** CHANGE *** PLACE PARAMETERS FOR YOUR EFFECT HERE
  132.     
  133.     long                        direction;    // direction of blit.  0 for dim to bright, 255 for bright to dim
  134.         
  135.     TweenContainerRecord        percentage;
  136.     
  137.     // *** END CHANGE ***
  138. } EffectGlobals;
  139.  
  140. // --------------------------------------------------------------------------------------
  141. // DISPATCHER
  142. // --------------------------------------------------------------------------------------
  143. /************************************************************************************ 
  144.  *    This is the main dispatcher for our codec. All calls from the codec manager
  145.  *    will come through here, with a unique selector and corresponding parameter block.
  146.  *
  147.  *    This routine must be first in the code segment of the codec component.
  148.  *
  149.  *    We use the normal dispatcher rather than the codec dispatcher as we need to
  150.  *    implement the extra effects routines on top of the codec ones.
  151.  */
  152. /************************************************************************************/
  153. // Begin Dispatch Stuff
  154.  
  155. // Used by Component Dispatch Helper to call our routines
  156. #define CALLCOMPONENT_BASENAME()        EffectsFrame
  157. #define    CALLCOMPONENT_GLOBALS()            EffectGlobals * storage
  158.  
  159. // Used by Type's .k.h to create prototypes for our routines
  160. #define    IMAGECODEC_BASENAME()            CALLCOMPONENT_BASENAME()
  161. #define    IMAGECODEC_GLOBALS()            CALLCOMPONENT_GLOBALS()
  162.  
  163. // Used by SubType's .k.h to create prototypes for our routines
  164. #define    IMAGECODECEFFECT_BASENAME()        CALLCOMPONENT_BASENAME()
  165. #define    IMAGECODECEFFECT_GLOBALS()        CALLCOMPONENT_GLOBALS()
  166.  
  167. // Other defines for Component Dispatch Helper
  168. #define COMPONENT_DISPATCH_FILE            "EffectDispatch.h"    // describes what to dispatch
  169. #define    GET_DELEGATE_COMPONENT()        (storage->delegate)    // how to find delegate component
  170.  
  171. #define COMPONENT_UPP_SELECT_ROOT()        ImageCodec            // root for Type's UPP_PREFIX and SELECT_PREFIX        
  172.  
  173. #include "Components.k.h"                // StdComponent's .k.h
  174. #include "ImageCodec.k.h"                // Type's .k.h
  175. #include "ComponentDispatchHelper.c"    // make our dispatcher and cando
  176.  
  177. // End Dispatch Stuff
  178. /************************************************************************************/
  179.  
  180. // --------------------------------------------------------------------------------------
  181. // MULTIPLE BIT-DEPTH AND PIXEL FORMATS
  182. //    For clarity/reuse sake, the drawing code is being kept separate from the component
  183. //    interface code.
  184. // --------------------------------------------------------------------------------------
  185.  
  186.  
  187. // 16BE555
  188. #define EffectFilter16 EffectFilter16BE555
  189. #define srcIs16BE555 1
  190. #define dstIs16BE555 1
  191. #include "EffectFilter16.c"
  192. #undef EffectFilter16
  193. #undef srcIs16BE555
  194. #undef dstIs16BE555
  195.  
  196. #if NON_MAC_PIXEL_FORMATS
  197. // 16LE555
  198. #define EffectFilter16 EffectFilter16LE555
  199. #define srcIs16LE555 1
  200. #define dstIs16LE555 1
  201. #include "EffectFilter16.c"
  202. #undef EffectFilter16
  203. #undef srcIs16LE555
  204. #undef dstIs16LE555
  205.  
  206. // 16LE565
  207. #define EffectFilter16 EffectFilter16LE565
  208. #define srcIs16LE565 1
  209. #define dstIs16LE565 1
  210. #include "EffectFilter16.c"
  211. #undef EffectFilter16
  212. #undef srcIs16LE565
  213. #undef dstIs16LE565
  214.  
  215. #endif
  216.  
  217. // 32ARGB
  218. #define EffectFilter32 EffectFilter32ARGB
  219. #define srcIs32ARGB 1
  220. #define dstIs32ARGB 1
  221. #include "EffectFilter32.c"
  222. #undef EffectFilter32
  223. #undef srcIs32ARGB
  224. #undef dstIs32ARGB
  225. #if NON_MAC_PIXEL_FORMATS
  226. // 32BGRA
  227. #define EffectFilter32 EffectFilter32BGRA
  228. #define srcIs32BGRA 1
  229. #define dstIs32BGRA 1
  230. #include "EffectFilter32.c"
  231. #undef EffectFilter32
  232. #undef srcIs32BGRA
  233. #undef dstIs32BGRA
  234. // 32RGBA
  235. #define EffectFilter32 EffectFilter32RGBA
  236. #define srcIs32RGBA 1
  237. #define dstIs32RGBA 1
  238. #include "EffectFilter32.c"
  239. #undef EffectFilter32
  240. #undef srcIs32RGBA
  241. #undef dstIs32RGBA
  242. // 32ABGR
  243. #define EffectFilter32 EffectFilter32ABGR
  244. #define srcIs32ABGR 1
  245. #define dstIs32ABGR 1
  246. #include "EffectFilter32.c"
  247. #undef EffectFilter32
  248. #undef srcIs32ABGR
  249. #undef dstIs32ABGR
  250. #endif
  251.  
  252. // --------------------------------------------------------------------------------------
  253. // INTERNAL ROUTINES
  254. //    For clarity/reuse sake, the drawing code is being kept separate from the component
  255. //    interface code.
  256. // --------------------------------------------------------------------------------------
  257.  
  258.  
  259. static OSErr RequestImageFormat(
  260.                                 EffectGlobals*    glob,     // input: globals for rendering
  261.                                 EffectSourcePtr         source,     // input: source to potentially convert
  262.                                 short                    width,        // input: desired width
  263.                                 short                    height,        // input: desired height
  264.                                 OSType                    pixelFormat)// input: desired pixel format (depth & format)
  265. /*
  266.     If the data is already in the requested height and depth, returns.
  267.     Otherwise, calls decompression to get it into the format we can handle
  268. */
  269. {
  270.     OSErr                    err = noErr;
  271.     CDSequenceDataSourcePtr    sourceData = source->source.image;
  272.     ImageDescriptionHandle    curDesc = (ImageDescriptionHandle) sourceData->dataDescription;
  273.     ImageDescriptionHandle    newDesc = nil;
  274.     ImageDescriptionPtr        dp;
  275.  
  276.     dp = *curDesc;
  277.     if (
  278.         (source->effectType == kEffectRawSource) && 
  279.         ( ((dp->cType == kRawCodecType) && (dp->depth == (short)pixelFormat)) || ( dp->cType == pixelFormat) ) &&
  280.  
  281.         (dp->width == width) && 
  282.         (dp->height == height))
  283.     {
  284.         /* already got what we need */
  285.         return noErr;
  286.     }
  287.  
  288.     // otherwise, call the ICM to convert to desired data format
  289.     newDesc = (ImageDescriptionHandle) NewHandleClear(sizeof(ImageDescription));
  290.     err = MemError();
  291.  
  292.     if (err == noErr)
  293.     {
  294.         short pixelSize = QTGetPixelSize(pixelFormat);
  295.  
  296.  
  297.  
  298.         dp = *newDesc;
  299. #if ! NON_MAC_PIXEL_FORMATS
  300.  
  301.         if ((pixelFormat >> 24) != 0) {
  302.  
  303.             // non-Mac format
  304.  
  305.             dp->cType             = pixelFormat;
  306.  
  307.             dp->depth             = pixelSize;
  308.  
  309.         } else     {
  310.  
  311.             dp->cType             = kRawCodecType;
  312.  
  313.             dp->depth             = pixelFormat;
  314.  
  315.         }
  316.  
  317. #else
  318.  
  319.         dp->cType             = pixelFormat;
  320.  
  321.         dp->depth             = pixelSize;
  322.  
  323. #endif
  324.  
  325.         dp->width  = width;
  326.         dp->height = height;
  327.         dp->clutID = -1;
  328.         
  329.         /* the source is a stacked effect - or one in a format we can't handle. */
  330.         /* pass it off to the Generic Effect to convert */
  331.         /* it to a normal source */
  332.         err = ImageCodecEffectConvertEffectSourceToFormat(glob->target, source, newDesc);
  333.  
  334.         if (newDesc)
  335.         {
  336.             DisposeHandle((Handle) newDesc);
  337.         }
  338.     }
  339.  
  340.     return err;
  341.     
  342. } // RequestImageFormat
  343.  
  344. // --------------------------------------------------------------------------------------
  345. static long BlitterPreflight(BlitGlobals    *glob,     // input: globals for rendering
  346.                              short            width,     // input: width of data
  347.                              short            height, // input: height of data
  348.                              long            *depth)    // input/output: depth of data
  349. {
  350.     // *** CHANGE *** If your effect handles different bit depths, change this code to return
  351.     // what bit depths you want.
  352.     
  353.     // our blitter can handle 16 and 32 bit deep -- otherwise, we request a change to 16 bit
  354.     switch (*depth)
  355.     {
  356.         case 16:
  357.         case 32:
  358.             break;
  359.         
  360.         default:
  361.             *depth = 16;
  362.             break;
  363.     }
  364.     // *** END CHANGE ***
  365.  
  366.     // save away the actual depth we are running at
  367.     glob->width     = width;
  368.     glob->height    = height;    
  369.     glob->destDepth = *depth;
  370.     
  371.     return noErr;
  372.     
  373. } // BlitterPreflight
  374.  
  375. // --------------------------------------------------------------------------------------
  376. static long BlitterSetSource(EffectGlobals                *glob,             // input: our globals
  377.                              long                         sourceNumber,    // input: source index to set
  378.                              EffectSourcePtr            source)            // input: source value
  379. {
  380.     OSErr    err = noErr;
  381.  
  382.     if (sourceNumber >= kMaxSources)
  383.     {
  384.         // too many sources for us to handle
  385.         err = -1;
  386.     }
  387.     else
  388.     { 
  389.         // a source we can handle, save it away
  390.         err = RequestImageFormat(glob, source, glob->blitter.width, glob->blitter.height, glob->blitter.dstPixelFormat);
  391.         if (err == noErr)
  392.         {
  393.             glob->blitter.sources[sourceNumber].src = source->source.image;
  394.         }
  395.         else
  396.         {
  397.             glob->blitter.sources[sourceNumber].src = nil;
  398.         }
  399.     }
  400.         
  401.     return (err);
  402.     
  403. } // BlitterSetSource
  404.  
  405.  
  406. // --------------------------------------------------------------------------------------
  407. static long BlitterSetDest(BlitGlobals    *glob,         // input: our globals
  408.                            PixMap        *dstPixMap, // input: pixels we will draw into
  409.                            Rect            *dstRect)    // input: area of pixels we will draw into
  410. {
  411.     OSErr    result = noErr;
  412.     long    offsetH,offsetV;
  413.     char    *baseAddr;
  414.     OSType                dstPixelFormat;
  415.  
  416.  
  417.  
  418.     dstPixelFormat = GETPIXMAPPIXELFORMAT(dstPixMap);
  419.  
  420.     
  421.  
  422.     glob->dstPixelFormat = dstPixelFormat;
  423.  
  424.  
  425.  
  426.  
  427.     // *** CHANGE *** If your effect handles different bit depths, change this code
  428.     /* adjust the destination baseaddress to be at the beginning of the desired rect */
  429.     offsetH = (dstRect->left - dstPixMap->bounds.left);
  430.     if (dstPixMap->pixelSize == 16)
  431.     {
  432.         offsetH <<= 1;                    /* 1 pixel = 2 bytes */
  433.     }
  434.     else
  435.     {
  436.         if (dstPixMap->pixelSize == 32)
  437.         {
  438.             offsetH <<= 2;                    /* 1 pixel = 4 bytes */
  439.         }
  440.         else
  441.         {
  442.             result = -1;                    /* a data format we can't handle */
  443.         }
  444.     }
  445.     // *** END CHANGE ***
  446.     
  447.     offsetV = (dstRect->top - dstPixMap->bounds.top) * dstPixMap->rowBytes;
  448.     baseAddr = dstPixMap->baseAddr + offsetH + offsetV;
  449.  
  450.     glob->dstBaseAddr = baseAddr;
  451.     glob->dstRowBytes = dstPixMap->rowBytes;
  452.  
  453.     return result;
  454.     
  455. } // BlitterSetDest
  456.  
  457.  
  458. // --------------------------------------------------------------------------------------
  459. static long BlitterRenderFrame(BlitGlobals    *glob)        // input: our globals
  460. {
  461.     SInt8            mmuMode;
  462.  
  463.     // render with proper memory mode
  464.     mmuMode = true32b;
  465.     SwapMMUMode(&mmuMode);
  466.     
  467.     // convert data into base/size
  468.     {
  469.         short    i;
  470.         
  471.         for (i = 0; i < kMaxSources; ++i)
  472.         {
  473.             if (glob->sources[i].src)
  474.             {
  475.                 glob->sources[i].srcBaseAddr = glob->sources[i].src->dataPtr;
  476.                 glob->sources[i].srcRowBytes = glob->sources[i].src->dataSize / glob->height;
  477.             }
  478.         }
  479.     }
  480.         
  481.     // *** CHANGE *** If your effect handles different bit depths, write other bit depth routines and
  482.     // call them from here
  483.     
  484.     // do the actual render
  485.     switch (glob->dstPixelFormat)
  486.     {
  487.         case k32ARGBPixelFormat:
  488.             EffectFilter32ARGB(glob);
  489.             break;
  490. #if NON_MAC_PIXEL_FORMATS
  491.         case k32ABGRPixelFormat:
  492.             EffectFilter32ABGR(glob); break;
  493.         case k32BGRAPixelFormat:     // we know how to do these pixel formats
  494.             EffectFilter32BGRA(glob); break;
  495.         case k32RGBAPixelFormat:
  496.             EffectFilter32RGBA(glob); break;
  497. #endif
  498.         case k16BE555PixelFormat:
  499.             EffectFilter16BE555(glob);
  500.             break;
  501. #if NON_MAC_PIXEL_FORMATS
  502.         case k16LE565PixelFormat:
  503.             EffectFilter16LE565(glob); break;
  504.         case k16LE555PixelFormat:
  505.             EffectFilter16LE555(glob); break;
  506. #endif
  507.     }
  508.     // *** END CHANGE ***
  509.  
  510.     SwapMMUMode(&mmuMode);
  511.     
  512.     return noErr;
  513.     
  514. } // BlitterRenderFrame
  515.  
  516.  
  517. // --------------------------------------------------------------------------------------
  518. // COMPONENT ENTRY POINTS
  519. // --------------------------------------------------------------------------------------
  520.  
  521.  
  522. #define kNumPixelFormatsSupported 0x20
  523.  
  524. pascal ComponentResult EffectsFrameOpen(EffectGlobals        *glob,    // input/output: our globals
  525.                                        ComponentInstance    self)    // input: reference to ourself
  526. /*
  527.     This is called once per instance of our component.  Allocate our storage at
  528.     this point.  If we have any shared storage, we would check here to make sure
  529.     it exists, else create it.
  530. */
  531. {
  532.     ComponentResult    result;
  533.     
  534.     result = noErr;
  535.         
  536.     // first, allocate our local storage
  537.     if ((glob = (EffectGlobals*) NewPtrClear(sizeof(EffectGlobals)))==nil)
  538.     {
  539.         result = MemError();
  540.         goto bail;
  541.     }
  542.     
  543.     SetComponentInstanceStorage(self, (Handle) glob);
  544.     
  545.     // we are ourselves, and the current top of chain is us
  546.     glob->self = self;
  547.     glob->target = self;
  548.     glob->wantedDestinationPixelTypeH = (OSType **) NewHandleClear(sizeof(OSType) * (kNumPixelFormatsSupported + 1));
  549.     
  550.     // open the generic effect, this will handle effects we can't handle ourselves
  551.     result = OpenADefaultComponent(decompressorComponentType, kEffectGenericType, &glob->delegate);
  552.     if (result)
  553.         goto bail;
  554.         
  555.     // set up the target for the components below us
  556.     EffectsFrameTarget(glob, self);
  557.  
  558. bail:
  559.     return(result);
  560.     
  561. } // EffectsFrameOpen
  562.  
  563.  
  564. // --------------------------------------------------------------------------------------
  565. // Called each time an instance of our component is going away.  Toss anything we allocated.
  566. pascal ComponentResult EffectsFrameClose(EffectGlobals        *glob,    // input: our globals
  567.                                         ComponentInstance    self)    // input: reference to ourself
  568. {
  569. #pragma unused (self)
  570.  
  571.     if (glob)
  572.     {
  573.         /*     *** CHANGE *** DISPOSE OF YOUR TWEENERS */
  574.         DisposeTweenRecord(&glob->percentage);
  575.  
  576.         /* *** END CHANGE *** */
  577.  
  578.  
  579.  
  580.         DisposeTweenGlobals(&glob->tweenGlobals);
  581.  
  582.         CloseComponent(glob->delegate);
  583.  
  584.  
  585.         DisposeHandle((Handle) glob->wantedDestinationPixelTypeH);
  586.  
  587.  
  588.         DisposePtr((Ptr) glob);
  589.     }
  590.     return(noErr);
  591.     
  592. } // EffectsFrameClose
  593.  
  594.  
  595. // --------------------------------------------------------------------------------------
  596.  
  597. pascal ComponentResult EffectsFrameTarget(EffectGlobals        *glob,    // input: our globals
  598.                                           ComponentInstance target)    // input: reference to new top of chain
  599. /*
  600.     Called when there is a new top of the calling chain.  Remember that ourselves, and tell
  601.     those below us as well.
  602. */
  603. {
  604.     // remember who is top of chain
  605.     glob->target = target;
  606.     
  607.     // and tell folks below us, too.
  608.     ComponentSetTarget(glob->delegate, target);
  609.     
  610.     return(noErr);
  611.     
  612. } // EffectsFrameTarget
  613.  
  614.  
  615. // --------------------------------------------------------------------------------------
  616.  
  617. pascal ComponentResult EffectsFrameVersion(EffectGlobals    *glob)        // input: our globals
  618. /*
  619.     Called to obtain the version of our component.
  620. */
  621. {
  622. #pragma unused (glob)
  623.     
  624.     return kDimmerEffectVersion;
  625.     
  626. } // EffectsFrameVersion
  627.  
  628.  
  629. // --------------------------------------------------------------------------------------
  630. //    Called to prepare for a sequence of frames.  
  631. //    Return in p->capabilities anything in particular your effect requires, such as 
  632. //    limitations on bitdepth.
  633. pascal long EffectsFrameEffectSetup(EffectGlobals            *glob,     // input: our globals
  634.                                      CodecDecompressParams    *p)        // input: information about the thing being decompressed
  635.  
  636. {
  637.     CodecCapabilities     *capabilities = p->capabilities;
  638.     OSErr                err;
  639.     OSType                 *formats = *glob->wantedDestinationPixelTypeH;
  640.     long                wantedPixelSize = capabilities->wantedPixelSize;
  641.     OSType                dstPixelFormat;
  642.     
  643.     dstPixelFormat = GETPIXMAPPIXELFORMAT(&p->dstPixMap);
  644.  
  645.     
  646.  
  647.     switch (dstPixelFormat)
  648.     {
  649.         case k32ARGBPixelFormat:
  650.         case k16BE555PixelFormat:
  651. #if NON_MAC_PIXEL_FORMATS
  652.         case k32BGRAPixelFormat:     // we know how to do these pixel formats
  653.         case k32ABGRPixelFormat:
  654.         case k32RGBAPixelFormat:
  655.         case k16LE565PixelFormat:
  656.         case k16LE555PixelFormat:
  657. #endif
  658.             *formats++ = dstPixelFormat;
  659.             break;
  660.         default:                    // we prefer 16 over 32
  661. #if NON_MAC_PIXEL_FORMATS
  662.             *formats++ = k16LE555PixelFormat;
  663.             *formats++ = k16LE565PixelFormat;
  664.             *formats++ = k32BGRAPixelFormat;
  665.             *formats++ = k32RGBAPixelFormat;
  666.             *formats++ = k32ABGRPixelFormat;
  667. #endif
  668.             *formats++ = k16BE555PixelFormat;
  669.             *formats++ = k32ARGBPixelFormat;
  670.             break;
  671.     }
  672.  
  673.  
  674.  
  675.     // NOTE: 0 marks the end of the format list
  676.  
  677.     *formats++ = 0;
  678.  
  679.  
  680.     /* set up our blitter */
  681.     err = BlitterPreflight(&glob->blitter,
  682.                            (*p->imageDescription)->width,
  683.                            (*p->imageDescription)->height,
  684.                            &wantedPixelSize);
  685.     
  686.     capabilities->wantedPixelSize = 0;
  687.  
  688.     p->wantedDestinationPixelTypes = glob->wantedDestinationPixelTypeH;
  689.  
  690.  
  691.     return (err);
  692.     
  693. } // EffectsFrameEffectSetup
  694.  
  695. // --------------------------------------------------------------------------------------
  696.  
  697. pascal void GetIntegrityParam (EffectGlobals* glob, CodecDecompressParams* p)
  698. {
  699.     Ptr            data = p->data;
  700.     QTAtom        atom;
  701.     QTAtomID    atomID = 1;
  702.     long        actSize;
  703.     long        temp;
  704.     long        i;
  705.     
  706.     // Find the 'sden' atom
  707.     atom = QTFindChildByID((QTAtomContainer) &data,
  708.         kParentAtomIsContainer,
  709.         OSTypeConst('SrIn'),// The name of the parameter
  710.         atomID,             // The ID of the parameter
  711.         nil);
  712.  
  713.     // Copy the parameter value from the atom
  714.     if (QTCopyAtomDataToPtr((QTAtomContainer) &data, atom, false, sizeof(long),
  715.         &temp, &actSize)!=noErr)
  716.     {
  717.         // If the copy failed, use a default value for this parameter
  718.         ((glob->blitter).iIntegrity) = 10;
  719.     } else {
  720.         // Otherwise, the copy succeeded, so endian flip and store the parameter value
  721.         ((glob->blitter).iIntegrity) = temp;
  722.     }
  723.     
  724.     (glob->blitter).puiRandoms = (UInt8*)NewPtr (32768);
  725.     if ((glob->blitter).puiRandoms == NULL) {
  726.         DebugStr ("\ppuiRandoms is NULL!!!!");
  727.     }
  728.     
  729.     for (i = 0; i < 32768; i++) {
  730.         (glob->blitter).puiRandoms [ i ] = ((float)((UInt32)Random ()) * (float)temp) / 65535.0 * 4;
  731.         if ((glob->blitter).puiRandoms [ i ] > (temp * 4)) {
  732.             DebugStr ("\ppuiRandoms are wrong");
  733.         }
  734.     }
  735.     
  736.     (glob->blitter).puiBrightnessRoll = (UInt8*)NewPtr ((glob->blitter).height * 2);
  737.     if ((glob->blitter).puiBrightnessRoll == NULL) {
  738.         DebugStr ("\ppfBrightnessRoll is NULL!!!!");
  739.     }
  740.     
  741.     for (i = 0; i < (glob->blitter).height * 2; i++) {
  742.         double pi = 3.14159;
  743.         double fResult;
  744.         fResult = 0.5 - (0.5 * cos (2.0 * pi * (double)i / (double)((glob->blitter).height * 2)));
  745.         fResult *= fResult;
  746.         fResult *= fResult;
  747.         fResult *= fResult;
  748.         fResult = 0.2 - (0.2 * fResult);
  749.         glob->blitter.puiBrightnessRoll [ i ] = ((double)fResult * (double)255.0);
  750.     }
  751.     
  752.     glob->blitter.puiBRStart = glob->blitter.puiBrightnessRoll;
  753.     glob->blitter.puiBREnd = glob->blitter.puiBrightnessRoll + glob->blitter.height;
  754. /*    fDstGamma = (glob->blitter).fDstGamma;
  755.     
  756.     dstPixelFormat = GETPIXMAPPIXELFORMAT(&p->dstPixMap);
  757.     
  758.     if (dstPixelFormat == k16BE555PixelFormat) {
  759.         for (i = 0; i < 32; i++) {
  760.             (glob->blitter).pcDstGamma [ i ] = (UInt8)(pow (((double)i / 31.0), fDstGamma) * 31.0);
  761.         }
  762.     } else {
  763.         for (i = 0; i < 256; i++) {
  764.             (glob->blitter).pcDstGamma [ i ] = (UInt8)(pow (((double)i / 255.0), fDstGamma) * 255.0);
  765.         }
  766.     }*/
  767. }
  768.  
  769. // ----------
  770. //    Called for each frame, before the request to actually draw
  771. pascal long EffectsFrameEffectBegin(EffectGlobals            *glob,    // input: our globals
  772.                              CodecDecompressParams    *p,     // input: info about frame being drawn
  773.                              EffectsFrameParamsPtr    effect)    // input: info about this effect frame
  774. {
  775.     OSErr                    err = noErr;
  776.     EffectSourcePtr            source;
  777.     long                    numSources = 0;
  778.     wide                    percentage;
  779.  
  780.     #if kMaxAsyncFrames > 0
  781.         /* we can go async if we don't already have an effect scheduled */
  782.         if (glob->asyncCount < kMaxAsyncFrames)
  783.         {
  784.             glob->asyncCount++;
  785.             effect->doAsync = true;
  786.         }
  787.     #endif
  788.  
  789.     // dest changed? 
  790.     if (p->conditionFlags & 
  791.             (codecConditionNewClut+codecConditionFirstFrame+codecConditionNewDepth+codecConditionNewDestination+codecConditionNewTransform))
  792.     {
  793.         // re-scan the sources
  794.         glob->majorSourceChangeSeed = 0;
  795.  
  796.         // re-read the parameters
  797.         glob->frameNumber = 0;
  798.  
  799.         err = BlitterSetDest(&glob->blitter, &p->dstPixMap, &p->dstRect);
  800.         if (err != noErr)
  801.             goto bail;
  802.  
  803.     }
  804.  
  805.     // new sources?  make note of them!
  806.     if (p->majorSourceChangeSeed != glob->majorSourceChangeSeed)
  807.     {
  808.         // grab start of input chain for this effect
  809.         source = effect->source;
  810.  
  811.         /* we can play with up to kMaxSources sources, so go get them */
  812.         while (source != nil && numSources < kMaxSources)
  813.         {        
  814.             /* now give that source to our blitter */
  815.             err = BlitterSetSource(glob, numSources, source);
  816.             if (err != noErr)
  817.                 goto bail;
  818.                 
  819.             source = source->next;
  820.             ++numSources;
  821.         }
  822.  
  823.  
  824.  
  825.         glob->majorSourceChangeSeed = p->majorSourceChangeSeed;
  826.     }
  827.     
  828.     /* if this is a new frame, or the same frame with a new length, get rid of our old parameters & tweeners */    
  829.     if ((effect->frameTime.frameNumber != glob->frameNumber) || (effect->frameTime.virtualDuration != glob->virtualDuration) )
  830.     {
  831.         /*     *** CHANGE *** DISPOSE OF YOUR TWEENERS */
  832.         DisposeTweenRecord(&glob->percentage);
  833.         
  834.         /* *** END CHANGE *** */
  835.  
  836.  
  837.  
  838.         DisposeTweenGlobals(&glob->tweenGlobals);
  839.  
  840.         glob->initialized = false;
  841.         glob->frameNumber = effect->frameTime.frameNumber;
  842.         glob->virtualDuration = effect->frameTime.virtualDuration;
  843.     }
  844.  
  845.     // Read in effect parameters
  846.     if (!glob->initialized)
  847.     {
  848.         Ptr                     data = p->data;
  849.         OSErr                    err;
  850.         long                    index = 1;
  851.         
  852.         err = InitializeTweenGlobals(&glob->tweenGlobals, p);
  853.         if (err!=noErr)
  854.             goto bail;
  855.             
  856.         /*     *** CHANGE *** TIME TO READ IN PARAMETERS TO YOUR EFFECT:
  857.             You can read any number of atoms you wish from the container.  For example, you might have a 
  858.             'star' (start) and 'end ' (end) value.  They might be expressed as percentages, numbers, or other values.
  859.             Or, you might have multiple atoms of type 'para' (param) which would be read in by calling
  860.             QTFindChildByIndex with various index values.  If you want to know how many parameters of a given
  861.             type there are, call QTCountChildrenOfType.  These parameters are specific to your particular effect,
  862.             and will need to be placed there by whoever is authoring the title.
  863.             
  864.             If you require parameters, and they aren't there, return an error.  If you can default the values
  865.             if they are missing, do so and continue.  In general, I'd recommend having a default case unless
  866.             you really are unable to implement it for a technical reason.
  867.             
  868.             These parameters are those that apply to the effect itself.  Later, we'll translate some of these parameters
  869.             into how they relate to *where* in the effect we are.  For example, an effect that runs from a starting
  870.             percentage of 10 to an ending percentage of 90 will have 10 and 90 as parameters here.
  871.         */
  872.         
  873.         /* make our tweener, return if we already have it */
  874.         err = CreateTweenRecord(&glob->tweenGlobals, &glob->percentage, 
  875.                         kParameterUsagePercent, 1, 
  876.                         sizeof(Fixed), kTweenTypeFixed, (void*)0, (void*)fixed1,  
  877.                         effect->frameTime.virtualDuration);
  878.         if (err!=noErr)
  879.             goto bail;
  880.                         
  881.         GetIntegrityParam (glob, p);
  882.  
  883.  
  884.         /* *** END CHANGE *** */
  885.  
  886.  
  887.  
  888.         glob->initialized = true;
  889.     }
  890.     
  891.     /* determine the amount we are along the tween via the current time - start time */
  892.     percentage = effect->frameTime.value;
  893.     CompSub(&effect->frameTime.virtualStartTime, &percentage);
  894.         
  895.     
  896.     /*     Tween our parameters and get the current value for this frame, prepare to render
  897.         it when the RenderFrame happens. */
  898.     if (err == noErr)
  899.         {
  900.         Fixed    thePercentage;
  901.         
  902.         /* ***** CHANGE TO TWEEN YOUR EFFECTS PARAMETERS */
  903.         
  904.         if (glob->percentage.tween)
  905.             QTDoTween(glob->percentage.tween, percentage.lo, glob->percentage.tweenData, nil, nil, nil );
  906.         
  907.         thePercentage = **(Fixed**)(glob->percentage.tweenData);
  908.         // If we are before the half-way point of this transition, we should
  909.         // be fading the first source to black
  910.         if (thePercentage < fixed1/2)
  911.         {
  912.             (glob->blitter).direction = 1;
  913.             (glob->blitter).dimValue = FixedToInt(FixMul(IntToFixed(512), thePercentage));
  914.         }
  915.         // Otherwise, we are fading up onto the new source
  916.         else
  917.         {
  918.             (glob->blitter).direction = 0;
  919.             (glob->blitter).dimValue = FixedToInt(FixMul(IntToFixed(512), thePercentage)) - 255;
  920.         }
  921.         
  922.         (glob->blitter).puiBrightnessRoll++;
  923.         if ((glob->blitter).puiBrightnessRoll > (glob->blitter).puiBREnd) {
  924.             (glob->blitter).puiBrightnessRoll = (glob->blitter).puiBRStart;
  925.         }
  926.         
  927.         /* ***** END CHANGE */
  928.         }
  929.  
  930.     if (glob->tweenGlobals.atLeastOneTweener)
  931.         {
  932.         // this effect runs constantly
  933.         p->needUpdateOnTimeChange = true;
  934.         p->needUpdateOnSourceChange = false;
  935.         }
  936.     else
  937.         {
  938.         // this effect only needs to run when the sources actually change
  939.         p->needUpdateOnTimeChange = true; //false;
  940.         p->needUpdateOnSourceChange = false; //true;
  941.         }
  942.     
  943.         
  944. // EXCEPTION HANDLING
  945. bail:
  946.     #if kMaxAsyncFrames > 0
  947.         // if we didn't queue the frame, then remove it from used list
  948.         if (err != noErr)
  949.             glob->asyncCount--;
  950.     #endif
  951.     
  952.     return err;
  953.     
  954. } // EffectsFrameEffectBegin
  955.  
  956.  
  957. // --------------------------------------------------------------------------------------
  958. pascal long EffectsFrameEffectRenderFrame(EffectGlobals             *glob,         // input: our globals
  959.                                     EffectsFrameParamsPtr    effect)        // input: effect frame to be rendered
  960. /*
  961.     Start rendering of the given frame.
  962. */
  963. {
  964. #pragma unused (effect)
  965.  
  966.     /* render the frame */
  967.     BlitterRenderFrame(&glob->blitter);
  968.     
  969.     #if kMaxAsyncFrames > 0
  970.         glob->asyncCount--;
  971.     #endif
  972.  
  973.     return noErr;
  974.     
  975. } // EffectsFrameEffectRenderFrame
  976.  
  977.  
  978. // --------------------------------------------------------------------------------------
  979. pascal long EffectsFrameEffectCancel(EffectGlobals            *glob,         // input: our globals
  980.                                     EffectsFrameParamsPtr    effect)        // input: effect frame to be canceled
  981. /*
  982.     Halt rendering of the given frame, even if it is only partially completed.
  983. */
  984. {
  985. #pragma unused (effect)
  986. #pragma unused (glob)
  987.  
  988.     #if kMaxAsyncFrames > 0
  989.         glob->asyncCount--;
  990.     #endif
  991.  
  992.     return noErr;
  993.     
  994. } // EffectsFrameEffectCancel
  995.  
  996.  
  997. // ----------------------------------------------------------------------------------------
  998.  
  999. pascal ComponentResult EffectsFrameGetCodecInfo(EffectGlobals    *glob,
  1000.                                                 CodecInfo        *info)
  1001. /*
  1002.  *    CDGetCodecInfo allows us to return information about ourselves to the codec manager.
  1003.  *    
  1004.  *    There will be a tool for determining appropriate values for the accuracy, speed
  1005.  *    and level information. For now we estimate with scientific wild guessing.
  1006.  *
  1007.  *  The info is stored as a resource in the same file with our component.
  1008.  */
  1009. {
  1010.     OSErr err = noErr;
  1011.  
  1012.     if (info == nil)
  1013.     {
  1014.         err = paramErr;
  1015.     }
  1016.     else
  1017.     {
  1018.         CodecInfo **tempCodecInfo;
  1019.  
  1020.         err = GetComponentResource((Component) glob->self,
  1021.                                    codecInfoResourceType,
  1022.                                    kEffectcdciRes,
  1023.                                    (Handle *) &tempCodecInfo);
  1024.         if (err == noErr)
  1025.         {
  1026.             *info = **tempCodecInfo;
  1027.             DisposeHandle((Handle) tempCodecInfo);
  1028.         }
  1029.     }
  1030.  
  1031.     return err;
  1032.     
  1033. } // EffectsFrameGetCodecInfo
  1034.  
  1035.  
  1036. // ---------------------------------------------------------------------------------------------------------------------------
  1037. pascal ComponentResult EffectsFrameGetParameterListHandle(EffectGlobals    *glob,        // input: our globals
  1038.                                                          Handle            *theHandle)    // output: the parameter description for this effect
  1039. {
  1040.     OSErr                    err = noErr;
  1041.     
  1042.     err = GetComponentResource((Component) glob->self,
  1043.                                FOUR_CHAR_CODE('atms'),
  1044.                                kEffectatmsRes,
  1045.                                theHandle);
  1046.     
  1047.     return(err);
  1048.     
  1049. } // EffectsFrameGetParameterListHandle
  1050.  
  1051. // ----------------------------------------------------------------------------------------
  1052. pascal long EffectsFrameEffectGetSpeed(EffectGlobals * glob, QTAtomContainer parameters, Fixed *pFPS)
  1053. {
  1054. #pragma unused (glob, parameters)
  1055.  
  1056.     if (pFPS)
  1057.         *pFPS = IntToFixed(30);
  1058.         
  1059.     return noErr;
  1060.     
  1061. } // EffectsFrameEffectGetSpeed
  1062.  
  1063.  
  1064.